package com.zl.quickdoc.format.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.deepoove.poi.util.PoitlIOUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import com.zl.quickdoc.constant.QuickDocC;
import com.zl.quickdoc.format.IApiFormat;
import com.zl.quickdoc.model.ApiAction;
import com.zl.quickdoc.model.ApiDocument;
import com.zl.quickdoc.model.ApiModule;
import com.zl.quickdoc.model.DocCfgParam;
import com.zl.quickdoc.utils.JsonUtils;



/**
 * @author zhouliang
 */
public class ApiFormatWord extends ApiFormatBase implements IApiFormat {

    @Override
    public String formatType() {
        return QuickDocC.DOC_TYPE_WORD;
    }
    @Override
    public String templateName() {
        return QuickDocC.TEMPLATE_WORD;
    }
    
    @Override
    public void format(ApiDocument apiDoc,DocCfgParam cfg) throws Exception {
        InputStream is2 = null;
        File tFile = getTemplatePath(cfg, templateName());
        if(tFile.exists() && tFile.isFile()) {
            is2 = new FileInputStream(tFile);
        }else {
            is2 = getClass().getClassLoader().getResourceAsStream(QuickDocC.TEMPLATE_ROOT+QuickDocC.TEMPLATE_WORD);
        }
        try(InputStream is = is2){
            Map<String, Object> model = new HashMap<>();
            model.putAll(apiDoc.getProperties());
            
            List<List<String>> changes = joinChangeContent(apiDoc.getChangedata(),";;  ","\n","    ");
            List<Map<String,String>> rows = new ArrayList<>();
            for(List<String> x:changes) {
               Map<String,String> rowvo = new HashMap<>();
               rowvo.put("version", x.get(0));
               rowvo.put("remark", x.get(1));
               rowvo.put("changes", x.get(2));
               rows.add(rowvo);
            }
            model.put("changeList",rows);
            
            List<Map<String,Object>> apiModuleList = new ArrayList<>();
//            List<Map<String,Object>> apiModuleList2 = new ArrayList<>();
            for(ApiModule x:apiDoc.getApiModules()) {
               Map<String, Object> apiModuleMap = JsonUtils.getObjectMapper().convertValue(x, new TypeReference<Map<String, Object>>() {});
               List<Map<String, Object>> apiActions2 = new ArrayList<>();
               apiModuleMap.put("apiActions", apiActions2);
               apiModuleList.add(apiModuleMap);
               
               List<ApiAction> apiActions = x.getApiActions();
               for(int i=0;i<apiActions.size();i++) {
                   ApiAction a1= (ApiAction) apiActions.get(i);
                   Map<String, Object> apiActionMap = JsonUtils.getObjectMapper().convertValue(a1, new TypeReference<Map<String, Object>>() {});
                   
                   List<Map<String, Object>> req = new ArrayList<>();
                   List<Map<String, Object>> convertReq = JsonUtils.getObjectMapper().convertValue(a1.getReqParam(), new TypeReference<List<Map<String, Object>>>() {});
                   if(convertReq!=null) {
                       filedHandler(req, convertReq, "",true);
                   }
                   List<Map<String, Object>> res = new ArrayList<>();
                   List<Map<String, Object>> convertRes = JsonUtils.getObjectMapper().convertValue(a1.getResParam(), new TypeReference<List<Map<String, Object>>>() {});
                   if(convertRes!=null) {
                       filedHandler(res, convertRes, "",true);
                   }
                   if(StringUtils.isNotBlank(a1.getRequestValueSimple())) {
                       apiActionMap.put("requestValueSimple", JsonUtils.toFormatJson(JsonUtils.readTree(a1.getRequestValueSimple())));
                   }
                   if(StringUtils.isNotBlank(a1.getResponseValueSimple())) {
                       apiActionMap.put("responseValueSimple", JsonUtils.toFormatJson(JsonUtils.readTree(a1.getResponseValueSimple())));
                   }
                   apiActionMap.put("uris", (a1.getUris()!=null&&!a1.getUris().isEmpty())?a1.getUris().get(0):"");
                   apiActionMap.put("methods", (a1.getMethods()!=null&&!a1.getMethods().isEmpty())?a1.getMethods().get(0):"");
                   apiActionMap.put("convertReq", req);
                   apiActionMap.put("convertRes", res);
                   apiActionMap.put("moduleTitle",i == 0?x.getTitle():"");
                   apiActions2.add(apiActionMap);
               }
            }
            model.put("apiModules", apiModuleList);
            
            LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();//创建一个列表的规则
            Configure config = Configure.builder().useSpringEL().bind("changeList", policy)
                   .bind("convertReq", policy).bind("convertRes", policy)
                   .build();
            
            XWPFTemplate template = XWPFTemplate.compile(is,config);// 编译模板
            template.render(model);
            File outfile = new File(cfg.getApiPath(),this.getFileTitle(cfg)+".docx");
            template.writeToFile(outfile.getPath());
            PoitlIOUtils.closeQuietlyMulti(template,is);
            apiDoc.setOutputPath(outfile.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @SuppressWarnings("unchecked")
    private void filedHandler(List<Map<String, Object>> req, List<Map<String, Object>> fields,String blankstr,boolean topFlag) {
        if(fields==null || fields.isEmpty()) {
            return;
        }
        String blankstr1 = topFlag?"":blankstr;
        for(Map<String, Object> reqx1:fields) {
            reqx1.put("description",reqx1.get("description") != null?
                ((String)reqx1.get("description")).replace("<br>", "\n"):"");
            if(reqx1.get("showType") == null) {
                 reqx1.put("showType", "");
            }
            if(reqx1.get("require") == null) {
                reqx1.put("require", false);
            }
            if(reqx1.get("pathFlag") == null) {
                reqx1.put("pathFlag", false);
            }
            reqx1.put("name", blankstr1 + reqx1.get("name"));
            req.add(reqx1);
            List<Map<String, Object>> t = (List<Map<String, Object>>) reqx1.get("children");
            if(t != null && !t.isEmpty()) {
                reqx1.remove("children");
                reqx1.put("childrenFlag",true);
                filedHandler(req, t, (blankstr1+"   "), false); 
            }else {
                reqx1.put("childrenFlag",false);
            }
        }
    }
}
